// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ComboBoxExtensions.cs" company="Roman '4ux-nbIx' Novitsky">
//   Copyright (c) Roman '4ux-nbIx' Novitsky 2010
// </copyright>
// <summary>
//   Defines the ComboBoxExtensions type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace MtgMC
{
  #region Namespace Imports

  using System;
  using System.Collections;
  using System.Collections.Generic;
  using System.Globalization;
  using System.Linq;
  using System.Windows.Forms;

  #endregion


  /// <summary>
  /// Defines <see cref="ComboBox"/> class extension methods.
  /// </summary>
  public static class ComboBoxExtensions
  {
    #region Public Methods

    /// <summary>
    /// Gets the item.
    /// </summary>
    /// <typeparam name="TItem">
    /// The type of the item.
    /// </typeparam>
    /// <param name="comboBox">
    /// The combo box.
    /// </param>
    /// <param name="itemMessageName">
    /// Name of the item in an error message.
    /// </param>
    /// <param name="getItemName">
    /// The get item name method.
    /// </param>
    /// <param name="createItem">
    /// The create item method.
    /// </param>
    /// <returns>
    /// The combo box item.
    /// </returns>
    public static TItem GetItem<TItem>(
      this ComboBox comboBox, string itemMessageName, Func<TItem, string> getItemName, Func<string, TItem> createItem)
      where TItem : class
    {
      return GetItem(
        comboBox, ((IEnumerable)comboBox.DataSource).Cast<TItem>(), itemMessageName, getItemName, createItem);
    }


    /// <summary>
    /// Gets the item.
    /// </summary>
    /// <typeparam name="TItem">
    /// The type of the item.
    /// </typeparam>
    /// <param name="comboBox">
    /// The combo box.
    /// </param>
    /// <param name="dataSource">
    /// The data source.
    /// </param>
    /// <param name="itemMessageName">
    /// Name of the item in an error message.
    /// </param>
    /// <param name="getItemName">
    /// The get item name method.
    /// </param>
    /// <param name="createItem">
    /// The create item method.
    /// </param>
    /// <returns>
    /// The combo box item.
    /// </returns>
    public static TItem GetItem<TItem>(
      this ComboBox comboBox, 
      IEnumerable<TItem> dataSource, 
      string itemMessageName, 
      Func<TItem, string> getItemName, 
      Func<string, TItem> createItem) where TItem : class
    {
      if (comboBox.SelectedIndex >= 0)
      {
        return (TItem)comboBox.SelectedItem;
      }

      string itemName = comboBox.GetText();

      if (string.IsNullOrEmpty(itemName))
      {
        string messageFormat = string.Format(
          CultureInfo.CurrentCulture, 
          "Please specify the new {0} name or select an existing {1}.", 
          itemMessageName, 
          itemMessageName);

        MessageBox.Show(
          messageFormat, "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);

        return null;
      }

      if (dataSource.Any(t => getItemName(t) == itemName))
      {
        string messageFormat = string.Format(
          CultureInfo.CurrentCulture, "A {0} with specified name already exists.", itemMessageName);

        MessageBox.Show(
          messageFormat, "Error", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);

        return null;
      }

      return createItem(itemName);
    }


    /// <summary>
    /// Gets the text.
    /// </summary>
    /// <param name="control">
    /// The control.
    /// </param>
    /// <returns>
    /// The control text.
    /// </returns>
    public static string GetText(this Control control)
    {
      return control.Text.Trim();
    }


    /// <summary>
    /// Initializes the specified combo box.
    /// </summary>
    /// <typeparam name="TItem">
    /// The type of the item.
    /// </typeparam>
    /// <param name="comboBox">
    /// The combo box.
    /// </param>
    /// <param name="dataSource">
    /// The data source.
    /// </param>
    /// <param name="displayMember">
    /// The display member.
    /// </param>
    /// <param name="selectedItem">
    /// The selected item.
    /// </param>
    public static void Initialize<TItem>(
      this ComboBox comboBox, IEnumerable<TItem> dataSource, string displayMember, TItem selectedItem)
      where TItem : class
    {
      var items = new List<TItem>();

      if (dataSource != null)
      {
        items.AddRange(dataSource);
      }

      if (selectedItem != null && !items.Contains(selectedItem))
      {
        items.Insert(0, selectedItem);
      }

      comboBox.Text = null;
      comboBox.DataSource = items;

      if (!string.IsNullOrEmpty(displayMember))
      {
        comboBox.DisplayMember = displayMember;
      }

      if (selectedItem != null)
      {
        comboBox.SelectedItem = selectedItem;
      }
    }

    #endregion
  }
}